/*
 * @(#)NetworkUtils.java Dec 25, 2011 - 11:22:12 AM
 * 
 * Copyright 2011 Cin/UFPE/VSPEED
 */
package speed2010.andreza.vspeed.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Enumeration;

/**
 * @author <a href="mailto:andreza.lba@gmail.com">Andreza Leite de Alencar</a>
 */
public class NetworkUtils {
	/**
	 * Return the localhost ip address
	 * 
	 * @author <a href="mailto:andreza.lba@gmail.com">Andreza Leite de Alencar</a>
	 * @return
	 */
	public static String getLocalHostIpAddress() {
		String hostAddress = null;
		String gatewayNet = null;
		String gateway = null;
		Process result = null;

		try {
			String macCMD = "netstat -nr|grep default|grep UG|grep Sc|grep -v 'I'|awk '{print$2}'";
			String linuxCMD = "netstat -nr|grep '0.0.0.0'|grep UG|awk '{print$2}'";
			String winCMD = "netstat -nr";

			if (isMac()) {
				result = Runtime.getRuntime().exec(new String[]{"sh", "-c", macCMD});
				BufferedReader response = new BufferedReader(new InputStreamReader(result.getInputStream()));
				gateway = response.readLine();

			} else if (isLinux()) {
				result = Runtime.getRuntime().exec(new String[]{"sh", "-c", linuxCMD});
				BufferedReader response = new BufferedReader(new InputStreamReader(result.getInputStream()));
				gateway = response.readLine();
			} else if (isWindows()) {
				result = Runtime.getRuntime().exec(winCMD);
				BufferedReader response = new BufferedReader(new InputStreamReader(result.getInputStream()));

				String line = response.readLine();
				while (line != null) {
					if (line.contains("0.0.0.0")) {
						String s1 = line.replaceAll("\\s", ";");
						
						for (int i = 0; i < 100; i++) {
							s1 = replaceChar(s1,";",",");
							s1.replaceAll(";", ",");
							
							s1 = replaceChar(s1,",",";");
							s1.replaceAll(",", ";");
						}
						s1 = s1.replaceAll(",", ";");
						s1 = replaceChar(s1,";",",");
						s1 = s1.replaceAll(";", ",");
						s1 = replaceChar(s1,",",";");
						s1 = s1.replaceAll(";", ",");
						s1 = s1.replaceAll(",", ";");
						
						String[] routeArray = s1.split(";");
						if (routeArray[1].equals("0.0.0.0") && routeArray[2].equals("0.0.0.0")) {
							gateway = routeArray[3];
						}
					}
					line = response.readLine();
				}
			}

			if (gateway != null) {
				String[] dotAddress = gateway.split("\\.");
				gatewayNet = dotAddress[0].concat(".") + dotAddress[1].concat(".") + dotAddress[2];

				Enumeration<?> e = NetworkInterface.getNetworkInterfaces();
				while (e.hasMoreElements()) {
					NetworkInterface ni = (NetworkInterface) e.nextElement();
					Enumeration<?> e2 = ni.getInetAddresses();

					while (e2.hasMoreElements()) {
						InetAddress ip = (InetAddress) e2.nextElement();
						if (ip.getHostAddress().contains(gatewayNet)) {
							hostAddress = ip.getHostAddress();
						}
					}
				}
			}

			if (hostAddress == null) {
				hostAddress = InetAddress.getLocalHost().getHostAddress();
			}

		} catch (Exception e) {
			e.printStackTrace();
		}

		return hostAddress;
	}

	/**
	 * Return the localhost ip address
	 * 
	 * @author <a href="mailto:andreza.lba@gmail.com">Andreza Leite de Alencar</a>
	 * @param network
	 *            The newtork address
	 * @return
	 */
	public static String getHostIpAddressFromNetwork(String network) {
		String hostAddress = null;

		try {

			Enumeration<?> e = NetworkInterface.getNetworkInterfaces();
			while (e.hasMoreElements()) {
				NetworkInterface ni = (NetworkInterface) e.nextElement();
				Enumeration<?> e2 = ni.getInetAddresses();

				while (e2.hasMoreElements()) {
					InetAddress ip = (InetAddress) e2.nextElement();
					if (ip.getHostAddress().contains(network)) {
						hostAddress = ip.getHostAddress();
					}
				}
			}

			if (hostAddress == null) {
				hostAddress = InetAddress.getLocalHost().getHostAddress();
			}

		} catch (Exception e) {
			e.printStackTrace();
		}

		return hostAddress;
	}

	public static boolean isHostAlive(final String host) {
		boolean reachable = false;
		try {
			reachable = InetAddress.getByName(host).isReachable(4000);
		} catch (final UnknownHostException e) {
			e.printStackTrace();
		} catch (final IOException e) {
			e.printStackTrace();
		}

		return reachable;
	}

	public static boolean isConnectionAlive(final String host, final String port) {
		boolean result = true;

		try {
			final Socket sc = new Socket(host, Integer.valueOf(port));
			sc.close();
		} catch (final UnknownHostException e) {
			result = false;
		} catch (final IOException e) {
			result = false;
		}

		return result;
	}

	/**
	 * Verify that current Operation System is Windows
	 * 
	 * @return
	 */
	public static boolean isWindows() {
		final String os = System.getProperty("os.name").toLowerCase();

		return (os.indexOf("win") >= 0);
	}

	/**
	 * Verify that current Operation System is MacOS
	 * 
	 * @return
	 */
	public static boolean isMac() {
		final String os = System.getProperty("os.name").toLowerCase();

		return (os.indexOf("mac") >= 0);
	}

	/**
	 * Verify that current Operation System is MacOS
	 * 
	 * @return
	 */
	public static boolean isLinux() {
		final String os = System.getProperty("os.name").toLowerCase();

		return (os.indexOf("linux") >= 0);
	}

	/**
	 * @param s1
	 * @return
	 */
	private static String replaceChar(String s1, String char1, String char2) {
		int c = 0;
		while (c<100) {
			s1 = s1.replaceAll(char1+char1, char2);
			if (s1.contains(char1)) {
				s1 = s1.replaceAll(char1+char1, char2);
			}
			c++;
		}
		s1.replaceAll(char1, char2);
		return s1;
	}
}